#include "Texture.h"
#include "stb_image.h"
#include <iostream>
using namespace std;

typedef unsigned int uint;

Texture::Texture(unsigned int dim, unsigned int channels, unsigned int width, unsigned int height)
{
    setTexture(dim, channels, width, height);
}

Texture::Texture(const char *nm, uint dim, bool flip)
{
    setTexture(nm, dim, flip);
}

void Texture::setTexture(unsigned int dim, unsigned int channels, unsigned int width, unsigned int height)
{
    glGenTextures(1, &ID);
    glBindTexture(dim, ID);
    this->dim = dim;
    glTexImage2D(dim, 0, channels, width, height, 0, channels, GL_UNSIGNED_BYTE, NULL);
    setfliter(DEFAULT_FILTER, DEFAULT_FILTER);
}
void Texture::setTexture(const char *img_name, unsigned int dim, bool flip)
{
    load_img(img_name, dim, flip);
}

int Texture::load_img(const char *nm, uint dim, bool flip)
{
    glGenTextures(1, &ID);
    glBindTexture(dim, ID);
    this->dim = dim;
    int width, height, nrChannels;
    stbi_set_flip_vertically_on_load(flip);
    unsigned char *data = stbi_load(nm, &width, &height, &nrChannels, 0);
    GLenum format;
    if (nrChannels == 1)
        format = GL_RED;
    else if (nrChannels == 3)
        format = GL_RGB;
    else if (nrChannels == 4)
        format = GL_RGBA;
    if (data)
    {
        glTexImage2D(dim, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
        glGenerateMipmap(dim);
        stbi_image_free(data);
        setWrap();
        setfliter(DEFAULT_FILTER, DEFAULT_FILTER);
        return 1;
    }
    else
    {
        cout << "ERROR::load_texture_image" << endl;
        stbi_image_free(data);
        return 0;
    }
}

unsigned int Texture::id() const
{
    return ID;
}
unsigned int Texture::getDim() const
{
    return dim;
}

void Texture::setWrap(unsigned int wrap_X, unsigned int wrap_Y, unsigned int wrap_Z)
{
    glBindTexture(dim, ID);
    glTexParameteri(dim, GL_TEXTURE_WRAP_S, wrap_X);
    if (dim == GL_TEXTURE_1D)
        return;
    glTexParameteri(dim, GL_TEXTURE_WRAP_T, wrap_Y);
    if (dim == GL_TEXTURE_2D)
        return;
    glTexParameteri(dim, GL_TEXTURE_WRAP_R, wrap_Z);
}
void Texture::setborderColor(float *borderColor)
{
    glBindTexture(dim, ID);
    glTexParameterfv(dim, GL_TEXTURE_BORDER_COLOR, borderColor);
}
void Texture::setfliter(unsigned min_filter, unsigned mag_filter)
{
    glBindTexture(dim, ID);
    if (min_filter == DEFAULT_FILTER)
        min_filter = GL_LINEAR;
    if (mag_filter == DEFAULT_FILTER)
        mag_filter = GL_LINEAR;
    glTexParameteri(dim, GL_TEXTURE_MIN_FILTER, min_filter);
    glTexParameteri(dim, GL_TEXTURE_MAG_FILTER, mag_filter);
}

void Texture::bind() const
{
    glBindTexture(dim, ID);
}

void Texture::active(unsigned int texID)
{
    glActiveTexture(texID);
}